#ifndef Net_EpollDispatcher_INCLUDED
#define Net_EpollDispatcher_INCLUDED

#include "runnable.h"
#include "threadpool.h"
#include "mutex.h"
#include "epollclientsocket.h"
#include "thread.h"
#include "socket.h"
#include "event.h"
#include <vector>
#include <map>

using std::vector;
using std::map;

class EpollServer;
class EpollEventThread;

enum EPOLL_MODE
{
    EPOLLMODE_ET,       /// edge triggered, the fd must be nonblocked
    EPOLLMODE_LT        /// level triggered 
};

class EpollDispatcher: public Runnable
{
public:

    struct FdStat
    {
        FdStat():
            m_fd(INVALID_SOCKET),m_enqnum(0)
            ,m_timeout(0),m_client(NULL)
        {}

        void clear()
        {
            m_fd = INVALID_SOCKET;
            m_enqnum = 0;
            m_timeout = 0;
            if ( m_client != NULL )
                m_client->m_running = false;
        }

        int             m_fd;
        // 加入队列多少次，dequeue时减去多少
        int             m_enqnum;
        unsigned int    m_timeout;
        EpollClientSocket *m_client;
    };

public:
    EpollDispatcher(ThreadPool& threadPool,
            EpollClientFactory& factory,
            unsigned int fdTimeoutSecond = 0);
        /// Creates the EpollDispatcher.
    
    ~EpollDispatcher();
    
    virtual void run();
        
    void enqueue(int fd);
    
    void stop();

    void setEpollServer(EpollServer* server);
        /// needed when detect timeout or error fd to notify epollserver to stop watch
        /// optional to set
    
    void setEpollEventThread(EpollEventThread* thread);
        /// needed when detect timeout or error fd to notify epollserver to stop watch
        /// optional to set
    
    /// monitor info no useful
    int queueSize() const
    {
        ScopedMutex lock(&m_queueMutex);
        return m_queuesize;
    }
    
private:
    void dequeue(int fd);
    
    bool checkCloseFd(int fd);
        /// check timeout fd
        /// return ture if timeout

    void resetQueueSize();

private:
    friend class EpollServer;
    friend class EpollEventThread;
    EpollDispatcher();
    EpollDispatcher(const EpollDispatcher&);
    EpollDispatcher& operator = (const EpollDispatcher&);

private:
    mutable Mutex                   m_queueMutex;
    vector<FdStat*>                 m_queue;
    
    ThreadPool&                     m_threadPool;
    EpollClientFactory&             m_factory;
    Thread                          m_thread;
    
    bool                            m_stopped;
        /// exit control
    EpollServer*                    m_epollServer;
    EpollEventThread*               m_epollEventThread;
    /// 可在队列中处理的时间限制，同时也是ThreadPool工作线程的超时时间
    unsigned int                    m_timeout;
    int                             m_maxFd;
    int                             m_queuesize;
    bool                            m_resizing;

    Event                           m_event;
};

#endif




